package com.artisan.flight.controller;


import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.PromptChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;

import java.nio.charset.StandardCharsets;
import java.time.LocalDate;


/**
 * AI 对话控制器
 * <p>
 * 提供三种不同的 ChatClient 实例，演示：
 * 1. 字符串方式配置系统提示词
 * 2. Resource 方式加载外部文件
 * 3. 增强版 Resource 方式 + 对话记忆 + 日志记录
 *
 */
@RestController
@CrossOrigin
public class OpenAiController2 {

    ChatClient chatClient;
    ChatClient chatClientFromResource;
    /**
     * 构造函数：创建三种不同配置方式的 ChatClient
     *
     * @param chatClientBuilder            Spring AI 提供的 ChatClient 构建器
     * @param systemPromptResource         基础系统提示词文件资源
     * @param enhancedSystemPromptResource 增强版系统提示词文件资源
     * @param chatMemory                   对话记忆存储
     */
    public OpenAiController2(
            ChatClient.Builder chatClientBuilder,
            @Value("classpath:prompts/system-prompt.txt") Resource systemPromptResource,
            @Value("classpath:prompts/system-prompt-enhanced.txt") Resource enhancedSystemPromptResource,
            ChatMemory chatMemory
    ) {
        // 方式一：直接使用字符串配置系统提示词（无记忆、无日志）
        this.chatClient = chatClientBuilder
                .defaultSystem("""
						##角色
                          您是"Artisan"航空公司的客户聊天支持代理。请以友好、乐于助人且愉快的方式来回复。
                          您正在通过在线聊天系统与客户互动。
                        ##要求
                          1.在涉及增删改（除了查询）function-call前，必须等用户回复"确认"后再调用tool。
                          2.请讲中文。

                          今天的日期是 {current_date}.
					""")
                .defaultAdvisors(
                        // 1. 对话记忆 Advisor：自动管理对话历史
                        PromptChatMemoryAdvisor.builder(chatMemory).build(),
                        // 2. 日志记录 Advisor：记录请求和响应
                        new SimpleLoggerAdvisor()
                )
                .build();

        // 方式二：使用 Resource 从外部文件加载系统提示词（基础版，无记忆、无日志）
        this.chatClientFromResource = chatClientBuilder
                .defaultSystem(systemPromptResource, StandardCharsets.UTF_8)
                .defaultAdvisors(
                        // 1. 对话记忆 Advisor：自动管理对话历史
                        PromptChatMemoryAdvisor.builder(chatMemory).build(),
                        // 2. 日志记录 Advisor：记录请求和响应
                        new SimpleLoggerAdvisor()
                )
                .build();

    }


    /**
     * 方式一：基础对话（无记忆、无日志）
     * 访问：GET http://localhost:8080/ai/generateStreamAsString?message=你好
     */
    @CrossOrigin
    @GetMapping(value = "/ai/generateStreamAsString2", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> generateStreamAsString(
            @RequestParam(value = "message", defaultValue = "讲个笑话") String message) {

        return chatClient.prompt()
                .user(message)
                // 动态参数注入
                .system(promptSystemSpec -> promptSystemSpec.param("current_date", LocalDate.now()))
                .stream()
                .content();
    }

    /**
     * 方式二：使用从外部文件加载的基础系统提示词（无记忆、无日志）
     * 访问：GET http://localhost:8080/ai/generateStreamFromResource?message=你好
     */
    @CrossOrigin
    @GetMapping(value = "/ai/generateStreamFromResource2", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> generateStreamFromResource(
            @RequestParam(value = "message", defaultValue = "讲个笑话") String message) {

        return chatClientFromResource.prompt()
                .user(message)
                // 动态参数注入
                .system(promptSystemSpec -> promptSystemSpec.param("current_date", LocalDate.now()))
                .stream()
                .content();
    }

}
